package common

import (
	"bytes"
	"crypto/rand"
	"errors"
	"fmt"
)

func NewPadResult(data []byte, mode string, blockSize int) ([]byte, error) {
	switch mode {
	case "pkc":
		return pkcs7Pad(data, blockSize), nil
	case "zero":
		return zeroPad(data, blockSize), nil
	case "iso":
		return iso10126Pad(data, blockSize), nil
	case "no":
		return noPad(data), nil
	default:
		return nil, errors.New("模式错误")
	}
}

func NewUnPadResult(data []byte, mode string) ([]byte, error) {
	switch mode {
	case "pkc":
		return pkcs7Unpad(data), nil
	case "zero":
		return zeroUnpad(data), nil
	case "iso":
		return iso10126Unpad(data)
	case "no":
		return noPad(data), nil
	default:
		return nil, errors.New("模式错误")
	}
}
func noPad(data []byte) []byte {
	return data
}
func pkcs7Pad(data []byte, blockSize int) []byte {
	padding := blockSize - len(data)%blockSize
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(data, padText...)
}
func pkcs7Unpad(data []byte) []byte {
	length := len(data)
	unpadding := int(data[length-1])
	return data[:length-unpadding]
}

func zeroPad(data []byte, blockSize int) []byte {
	padding := blockSize - len(data)%blockSize
	return append(data, bytes.Repeat([]byte{0}, padding)...)
}

func zeroUnpad(data []byte) []byte {
	return bytes.TrimRight(data, "\x00")
}

func iso10126Pad(data []byte, blockSize int) []byte {
	padding := blockSize - len(data)%blockSize
	padText := make([]byte, padding)
	_, err := rand.Read(padText[:padding-1])
	if err != nil {
		panic(err)
	}
	padText[padding-1] = byte(padding)
	return append(data, padText...)
}

func iso10126Unpad(data []byte) ([]byte, error) {
	length := len(data)
	if length == 0 {
		return nil, fmt.Errorf("输入数据为空，无法进行去填充操作")
	}

	unpadding := int(data[length-1])
	if unpadding > length {
		return nil, fmt.Errorf("填充字节数大于数据长度，可能数据有误")
	}

	return data[:length-unpadding], nil
}
